package com.mybatis.crudservice.dao;

import com.fasterxml.jackson.databind.util.JSONPObject;
import com.mybatis.crudservice.enums.OperateType;
import com.mybatis.crudservice.mapper.EntityMapper;
import com.mybatis.crudservice.tools.EntityUtils;
import com.mybatis.crudservice.tools.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import static com.mybatis.crudservice.enums.ExceptionType.*;
import static com.mybatis.crudservice.tools.EntityUtils.getValue;
import static com.mybatis.crudservice.tools.CheckUtils.notNull;
import static com.mybatis.crudservice.tools.CheckUtils.compareSize;
import com.mybatis.crudservice.annotation.MyColumn;
import com.mybatis.crudservice.annotation.MyId;
import com.mybatis.crudservice.annotation.MyTable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;

/**
 * @ 描 述 : 增删改服务
 * @ 作 者 : 一念〃
 * @ 时 间 : 21:30 2019/6/6
 * @ 备 注 :
 */
@Slf4j
@Component
public class EntityDao {

    @Value("${mybatis.type-aliases-package}")
    private String catalog;

    @Autowired
    private EntityMapper entityMapper;

    /**
     * 新增 - 返回受影响行数
     * @param entity 实体名称
     * @param data 插入的数据
     * @return
     * @throws Exception
     */
    public int insertReCount(String entity, Map<String,Object> data) throws Exception {
        Class<?> aClass = Class.forName(catalog + "." + entity);
        Object beans = JsonUtils.json2pojo(JsonUtils.MapToJsonStr(data), aClass);
        log.info("insertReCount ：" + beans);
        int count = entityMapper.insertReCount(getAnnotation(beans, OperateType.INSERTRECOUNT));
        log.info("insertReCount success, 受影响行数：" + count);
        return count;
    }

    /**
     * 修改 - 返回受影响行数
     * @param entity 实体名称
     * @param data 插入的数据
     * @return
     * @throws Exception
     */
    public int updateReCount(String entity,Map<String,Object> data) throws Exception {
        Class<?> aClass = Class.forName(catalog + "." + entity);
        Object beans = JsonUtils.json2pojo(JsonUtils.MapToJsonStr(data), aClass);
        log.info("updateReCount ：" + beans);
        int count = entityMapper.updateReCount(getAnnotation(beans, OperateType.UPDATERECOUNT));
        log.info("updateReCount success, 受影响行数：" + count);
        return count;
    }


    /**
     * 获取注解值
     * @param entity 实体类
     * @param type 操作类型
     * @return
     */
    private Map<String, Object> getAnnotation(Object entity, OperateType type) {
        Field [] fields = entity.getClass().getDeclaredFields();
        Class<?> clazz = entity.getClass();

        //表名校验
        notNull(entity.getClass().getAnnotation(MyTable.class), MYTABLE.getMessage());

        Map<String, Object> operate = new HashMap<String, Object>();
        operate.put("table_name", entity.getClass().getAnnotation(MyTable.class).value());

        switch (type) {
            //插入 - 返回受影响行数
            case INSERTRECOUNT:
                List key = new ArrayList();
                List value = new ArrayList();
                for (int i = 0; i < fields.length; i++) {
                    //获取列名和值
                    if (fields[i].getAnnotation(MyColumn.class) != null) {
                        key.add(fields[i].getAnnotation(MyColumn.class).value());
                        value.add(getValue(fields[i], clazz, entity));
                        continue;
                    }
                    //获取主键
                    if (fields[i].getAnnotation(MyId.class) != null) {
                        operate.put("KEY_ID", fields[i].getAnnotation(MyId.class).value());
                        operate.put("KEY_VALUE", getValue(fields[i], clazz, entity));
                        //此处对ID做处理 - 如果是32位UUID使用UUID
                        //Object val = UUID.randomUUID().toString().replaceAll("-", "");
                        //operate.put("KEY_VALUE", val);
                    }
                }
                //校验key和value
                compareSize(key.size(), value.size(), KEYEQVALUE.getMessage());
                operate.put("columns", key);
                operate.put("values", value);
                break;
            //修改 - 返回受影响行数
            case UPDATERECOUNT:
                List d = new ArrayList();
                for (int i = 0; i < fields.length; i++) {
                    //获取列名和值
                    Map<String, Object> map = new HashMap<>();
                    if (fields[i].getAnnotation(MyColumn.class) != null) {
                        map.put("COLUMN", fields[i].getAnnotation(MyColumn.class).value());
                        map.put("COL_VALUE", getValue(fields[i], clazz, entity));
                        d.add(map);
                        continue;
                    }
                    if (fields[i].getAnnotation(MyId.class) != null) {
                        operate.put("KEY_ID", fields[i].getAnnotation(MyId.class).value());
                        operate.put("KEY_VALUE", getValue(fields[i], clazz, entity));
                    }
                }
                operate.put("DATA", d);
                break;
        }
        return operate;
    }
}
